package com.moose.security.sevice;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Sets;
import com.moose.entity.sys.SysPermission;
import com.moose.entity.sys.SysRole;
import com.moose.entity.sys.SysUser;
import com.moose.security.permission.Permission;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 权限校验
 *
 * @author 唐国翔
 * @since 2018-11-07 16:38
 * <p>
 * 　　　　　　　　┏┓　　　┏┓+ +
 * 　　　　　　　┏┛┻━━━┛┻┓ + +
 * 　　　　　　　┃　　　　　　　┃
 * 　　　　　　　┃　　　━　　　┃ ++ + + +
 * 　　　　　　 ████━████ ┃+
 * 　　　　　　　┃　　　　　　　┃ +
 * 　　　　　　　┃　　　┻　　　┃
 * 　　　　　　　┃　　　　　　　┃ + +
 * 　　　　　　　┗━┓　　　  ┏━┛
 * 　　　　　　　　　┃　　　┃
 * 　　　　　　　　　┃　　　┃ + + + +
 * 　　　　　　　　　┃　　　┃　　　　Code is far away from bug with the animal protecting
 * 　　　　　　　　　┃　　　┃ + 　　　　神兽保佑,代码无bug
 * 　　　　　　　　　┃　　　┃
 * 　　　　　　　　　┃　　　┃　　+
 * 　　　　　　　　　┃　 　　┗━━━┓ + +
 * 　　　　　　　　　┃ 　　　　　　　┣┓
 * 　　　　　　　　　┃ 　　　　　　　┏┛
 * 　　　　　　　　　┗┓┓┏━┳┓┏┛ + + + +
 * 　　　　　　　　　　┃┫┫　┃┫┫
 * 　　　　　　　　　　┗┻┛　┗┻┛+ + + +
 **/
@Component("permissionService")
public class PermissionService implements Permission {

    @Value("${server.servlet.context-path}")
    private String contextPath;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        boolean hasPermission = false;
        if (principal instanceof UserDetails) {
            try {
                SysUser sysUser = (SysUser) principal;
                //获取用户所有角色
                List<SysRole> roles = sysUser.getRoles();

                //系统管理员角色拥有全权限
                if (roles.stream().anyMatch(e -> "系统管理员".equals(e.getRoleName()))) {
                    return true;
                }

                //读取用户所拥有的所有权限
                Set<String> urls = Sets.newHashSet();
                for (SysRole role : roles) {
                    urls.addAll(role.getPermissions().parallelStream().map(SysPermission::getUrl).collect(Collectors.toSet()));
                }

                //过滤用户权限
                for (String url : urls) {
                    if (StrUtil.isEmpty(url)) {
                        continue;
                    }
                    //去除项目配置访问根路径后进行匹配
                    if (antPathMatcher.match(url, StrUtil.replace(request.getRequestURI(), contextPath, StrUtil.EMPTY))) {
                        hasPermission = true;
                        break;
                    }
                }
            } catch (ClassCastException e) {
                return false;
            }
        }
        return hasPermission;
    }
}
